﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;

using Insesoft.Entities;
using InseSoft.UIControllers;
using Microsoft.Reporting.WinForms;

namespace Insesoft.UI.Procesos
{
    public partial class SolicitudCotizacionForm : BaseForm
    {
        #region Constructor

        public SolicitudCotizacionForm()
        {
            InitializeComponent();
        }

        #endregion

        #region Declarations

        private bool applied;
        private SolicitudCotizacion solicitudActual;
        private const string SolicitudCotizacionReport = "Insesoft.UI.Reports.rptSolicitudCotizacion.rdlc";
        private readonly SolicitudCotizacionController controller = new SolicitudCotizacionController();

        #endregion

        #region Event Handlers

        private void SolicitudCotizacionFormLoad(object sender, EventArgs e)
        {
            try
            {
                Cursor = Cursors.WaitCursor;
                ConfigureToolBar(toolStrip, ToolBarButtons.Save |
                                         ToolBarButtons.Delete |
                                         ToolBarButtons.New |
                                         ToolBarButtons.Search |
                                         ToolBarButtons.Approve |
                                         ToolBarButtons.Print |
                                         ToolBarButtons.Close);
                PopulateControls();
                Initialize();
            }
            finally
            {
                Cursor = Cursors.Arrow;
            }
        }

        private void ToolStripItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            switch ((ToolBarButtons)e.ClickedItem.Tag)
            {
                case ToolBarButtons.Save:
                    Save();
                    break;
                case ToolBarButtons.Delete:
                    Delete();
                    break;
                case ToolBarButtons.New:
                    Initialize();
                    break;
                case ToolBarButtons.Search:
                    Search();
                    break;
                case ToolBarButtons.Approve:
                    Apply();
                    break;
                case ToolBarButtons.Print:
                    Print();
                    break;
                case ToolBarButtons.Close:
                    Close();
                    break;
            }
        }

        private void CantidadesListBoxKeyDown(object sender, KeyEventArgs e)
        {
            if (!applied && e.KeyData == Keys.Delete && cantidadesListBox.SelectedItem != null)
            {
                var index = cantidadesListBox.SelectedIndex;
                cantidadesListBox.Items.RemoveAt(index);
                if (cantidadesListBox.Items.Count > 0)
                {
                    var newIdex = Math.Max(index - 1, cantidadesListBox.Items.Count - 1);
                    var item = cantidadesListBox.Items[newIdex];
                    cantidadesListBox.SelectedItem = item;
                }
            }
        }

        private void AgregarCantidadButtonClick(object sender, EventArgs e)
        {
            AgregarCantidad();
        }

        private void CantidadTextBoxKeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.Return)
                AgregarCantidad();
        }

        private void ClienteComboBoxSelectedIndexChanged(object sender, EventArgs e)
        {
            if (clienteComboBox.SelectedValue is int && clienteComboBox.SelectedIndex >= 0)
            {
                var cliente = clienteComboBox.SelectedItem as Cliente;
                if (cliente != null)
                {
                    clienteContactoTextBox.Text = cliente.ContactoNombre;
                    clienteCorreoTextBox.Text = cliente.ContactoCorreo;
                    clienteTelefonoTextBox.Text = cliente.ContactoTelefono;
                }
            }
            else
            {
                clienteContactoTextBox.Text = "";
                clienteCorreoTextBox.Text = "";
                clienteTelefonoTextBox.Text = "";
            }
        }

        #endregion

        #region Methods: Non-Public

        private void Print()
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                var parameters = new List<ReportParameter>();
                var solicitudCotizacionReport = CotizacionController.ConvertEntityToReport(solicitudActual);
                var data = new List<SolicitudCotizacionReport> { solicitudCotizacionReport };

                using (var form = new Reports.ReportViewerForm { ReportTitle = "Solicitud de Cotización" })
                {
                    form.BuildReport(data, "Solicitud", SolicitudCotizacionReport, parameters);
                    form.Show();
                }
            }
            catch (Exception ex)
            {
                DisplayError("No se pudo imprimir la solicitud de cotización.", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void Apply()
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                if (ValidateEntries())
                {
                    if (MessageBox.Show("¿Está seguro de aplicar la solicitud de cotización " + idLabel.Text + "?\r\nSi la aplica no podrá hacerle posteriores modificaciones", Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                    {
                        solicitudActual = Pack();
                        solicitudActual.Aplicada = true;
                        solicitudActual.Fecha = DateTime.Now;
                        controller.Save(solicitudActual);
                        fechaTextBox.Text = solicitudActual.Fecha.Value.ToString(FormatoFecha);
                        MessageBox.Show("La solicitud de cotización ha sido aplicada.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
                        applied = true;
                        EnableDisable();
                    }
                }
            }
            catch (Exception ex)
            {
                DisplayError("No se pudo aprobar la cotización.", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void Search()
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                var form = new SolCotSearchForm();
                if (form.ShowDialog() == DialogResult.OK)
                    Open(form.SearchResult);
            }
            catch (Exception ex)
            {
                DisplayError("No es posible realizar la búsqueda.", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void Open(SolicitudCotizacion solicitud)
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                UnPack(solicitud);
                EnableDisable();
            }
            catch (Exception ex)
            {
                DisplayError("No se pudo recuperar la cotización.", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void AgregarCantidad()
        {
            double value;
            if (double.TryParse(cantidadTextBox.Text, out value))
            {
                cantidadesListBox.Items.Add(cantidadTextBox.Text);
                cantidadTextBox.Text = "0";
            }
        }

        private void PopulateControls()
        {
            PopulateComboBox(clienteComboBox, controller.GetActive<Cliente>());
            PopulateComboBox(vendedorComboBox, controller.GetActive<Vendedor>());
            PopulateComboBox(materialComboBox, controller.GetActive<Material>());
            PopulateComboBox(lineaComboBox, controller.GetActive<Linea>());
            PopulateComboBox(tipoProductoComboBox, controller.GetActive<TipoProducto>());
        }

        private void Initialize()
        {
            // Reset cot variables
            applied = false;

            Initialize(Controls);
            vendedorComboBox.Focus();
            EnableDisable();
        }

        private static void Initialize(Control.ControlCollection pControls)
        {
            foreach (Control ctr in pControls)
            {
                if (ctr is TextBox)
                    ctr.Text = "";
                else if (ctr.GetType().ToString().IndexOf("Label") > -1)
                {
                    if (ctr.Tag != null && !string.IsNullOrEmpty(ctr.Tag.ToString()))
                        ctr.Text = ctr.Tag.ToString();
                }
                else if (ctr.GetType().ToString().IndexOf("ComboBox") > -1)
                {
                    var combo = (ComboBox)ctr;
                    combo.SelectedIndex = -1;
                    combo.SelectedIndex = -1;
                }
                else if (ctr.GetType().ToString().IndexOf("DateTimePicker") > -1)
                    ((DateTimePicker)ctr).Value = DateTime.Now;

                else if (ctr.GetType().ToString().IndexOf("CheckBox") > -1 || ctr.GetType().ToString().IndexOf("RadioButton") > -1)
                    ((CheckBox)ctr).Checked = false;

                else if (ctr is ListBox)
                    ((ListBox)ctr).Items.Clear();

                if (ctr.Controls.Count > 0)
                    Initialize(ctr.Controls);
            }
        }

        private void EnableDisable()
        {
            var solLoaded = (idLabel.Text != idLabel.Tag.ToString());

            foreach (ToolStripItem item in toolStrip.Items)
            {
                if (item.Tag != null)
                {
                    switch ((ToolBarButtons)item.Tag)
                    {
                        case ToolBarButtons.Execute:
                            item.Enabled = !applied;
                            break;
                        case ToolBarButtons.Delete:
                        case ToolBarButtons.Approve:
                            item.Enabled = solLoaded && !applied;
                            break;
                        case ToolBarButtons.Print:
                        case ToolBarButtons.Copy:
                            item.Enabled = solLoaded;
                            break;
                    }
                }
            }
            EnableDisableControls();
        }

        private void EnableDisableControls()
        {
            vendedorComboBox.Enabled = !applied;
            lineaComboBox.Enabled = !applied;
            clienteComboBox.Enabled = !applied;
            cotizacionGroupBox.Enabled = applied;
            EnableDisableProductGroupBox();
        }

        private void EnableDisableProductGroupBox()
        {
            foreach(Control control in productoGroupBox.Controls)
            {
                if (!(control is ListBox))
                    control.Enabled = !applied;
            }
        }

        private void Save()
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                solicitudActual = controller.Save(Pack());
                idLabel.Text = solicitudActual.Id.ToString();
                MessageBox.Show("La solicitud de cotización ha sido guardada.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
                EnableDisable();
            }
            catch (Exception ex)
            {
                DisplayError("No se pudo guardar la información.", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void Delete()
        {
            try
            {
                Cursor.Current = Cursors.WaitCursor;
                if (MessageBox.Show("¿Está seguro de eliminar la solicitud de cotización " + idLabel.Text + "?", Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) == DialogResult.Yes)
                {
                    controller.Delete(solicitudActual);
                    Initialize();
                    MessageBox.Show("La solicitud de cotización ha sido eliminada.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                DisplayError("No se pudo eliminar la información.", ex);
            }
            finally
            {
                Cursor.Current = Cursors.Default;
            }
        }

        private void UnPack(SolicitudCotizacion sol)
        {
            SetComboBoxValue(vendedorComboBox, sol.Vendedor);
            SetComboBoxValue(lineaComboBox, sol.Linea);
            SetComboBoxValue(clienteComboBox, sol.Cliente);
            SetComboBoxValue(tipoProductoComboBox, sol.TipoProducto);
            productoTextBox.Text = sol.Producto;
            SetDecimalValue(baseProductoTextBox, sol.ProductoBase);
            SetDecimalValue(alturaProductoTextBox, sol.ProductoAltura);
            SetDecimalValue(fondoProductoTextBox, sol.ProductoFondo);
            SetComboBoxValue(materialComboBox, sol.Material);
            SetIntegerValue(tintas1TextBox, sol.Tintas1Cara);
            SetIntegerValue(tintas2TextBox, sol.Tintas2Cara);
            SetDecimalValue(baseMaterialTextBox, sol.MaterialBase);
            SetDecimalValue(alturaMaterialTextBox, sol.MaterialAltura);
            SetDecimalValue(fondoMaterialTextBox, sol.MaterialFondo);
            cuatricromiaCheckBox.Checked = sol.Cuatricromia;
            troquelCheckBox.Checked = sol.Troquel;
            despieceCheckBox.Checked = sol.Despiece;
            UnpackCantidades(sol.Cantidades);
            observacionesTextBox.Text = sol.Observaciones;
            SetDecimalValue(rendimientoTextBox, sol.Rendimiento);
            SetDecimalValue(montajeTextBox, sol.Montaje);
            SetDecimalValue(cubrimientoTextBox, sol.Cubrimiento);
            SetIntegerValue(cotizacionTextBox, sol.CotizacionId);
            SetIntegerValue(idLabel, sol.Id);

            if (sol.Fecha.HasValue)
                fechaTextBox.Text = sol.Fecha.Value.ToString(FormatoFecha);

            applied = sol.Aplicada;
            solicitudActual = sol;
        }

        private SolicitudCotizacion Pack()
        {
            var solicitud = controller.GetOrNew<SolicitudCotizacion>(GetCurrentId(idLabel));
            solicitud.Empresa = ApplicationSession.Instance.Empresa;
            solicitud.Usuario = ApplicationSession.Instance.Usuario;
            solicitud.Vendedor = GetComboBoxItem<Vendedor>(vendedorComboBox);
            solicitud.Linea = GetComboBoxItem<Linea>(lineaComboBox);
            solicitud.Cliente = GetComboBoxItem<Cliente>(clienteComboBox);
            solicitud.TipoProducto = tipoProductoComboBox.SelectedItem as TipoProducto;
            solicitud.Producto = productoTextBox.Text.Trim();
            solicitud.ProductoBase = GetDecimalValue(baseProductoTextBox);
            solicitud.ProductoAltura = GetDecimalValue(alturaProductoTextBox);
            solicitud.ProductoFondo = GetDecimalValue(fondoProductoTextBox);
            solicitud.Material = GetComboBoxItem<Material>(materialComboBox);
            solicitud.Tintas1Cara = GetIntegerValue(tintas1TextBox);
            solicitud.Tintas2Cara = GetIntegerValue(tintas2TextBox);
            solicitud.MaterialBase = GetDecimalValue(baseMaterialTextBox);
            solicitud.MaterialAltura = GetDecimalValue(alturaMaterialTextBox);
            solicitud.MaterialFondo = GetDecimalValue(fondoMaterialTextBox);
            solicitud.Cuatricromia = cuatricromiaCheckBox.Checked;
            solicitud.Troquel = troquelCheckBox.Checked;
            solicitud.Despiece = despieceCheckBox.Checked;
            solicitud.Cantidades = PackCantidades();
            solicitud.Observaciones = observacionesTextBox.Text.Trim();
            solicitud.Rendimiento = GetDecimalValue(rendimientoTextBox);
            solicitud.Montaje = GetDecimalValue(montajeTextBox);
            solicitud.Cubrimiento = GetDecimalValue(cubrimientoTextBox);
            solicitud.CotizacionId = GetIntegerValue(cotizacionTextBox);
            solicitud.Aplicada = (solicitudActual == null) ? false : solicitudActual.Aplicada;

            if (idLabel.Text != idLabel.Tag.ToString())
                solicitud.Id = Convert.ToInt32(idLabel.Text);

            return solicitud;
        }

        private string PackCantidades()
        {
            var result = new StringBuilder();
            foreach (string item in cantidadesListBox.Items)
                result.Append(item + ",");

            return result.Length > 0 ? result.ToString().Substring(0, result.Length - 1) : "";
        }

        private void UnpackCantidades(string items)
        {
            cantidadesListBox.Items.Clear();
            if (!string.IsNullOrEmpty(items))
                cantidadesListBox.Items.AddRange(items.Split(','));
        }

        private bool ValidateEntries()
        {
            var msg = "";
            var functionReturnValue = false;

            if (vendedorComboBox.SelectedItem == null)
            {
                msg = "Falta ingresar el vendedor.";
                vendedorComboBox.Focus();
            }
            else if (lineaComboBox.SelectedItem == null)
            {
                msg = "Falta ingresar la línea.";
                lineaComboBox.Focus();
            }
            else if (clienteComboBox.SelectedItem == null)
            {
                msg = "Falta ingresar el cliente.";
                clienteComboBox.Focus();
            }
            else if (tipoProductoComboBox.SelectedItem == null)
            {
                msg = "Falta ingresar el Tipo de producto.";
                tipoProductoComboBox.Focus();
            }
            else if (string.IsNullOrEmpty(productoTextBox.Text.Trim()))
            {
                msg = "Falta ingresar el producto.";
                productoTextBox.Focus();
            }
            else if (materialComboBox.SelectedItem == null)
            {
                msg = "Falta ingresar el material.";
                materialComboBox.Focus();
            }

            else if (cantidadesListBox.Items.Count == 0)
            {
                msg = "Falta ingresar la(s) cantidad(es).";
                cantidadTextBox.Focus();
            }
            else
                functionReturnValue = true;

            if (!functionReturnValue)
                MessageBox.Show(msg, Text, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

            return functionReturnValue;
        }

        #endregion
    }
}
